﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kokomo.Mirror.PeFormat;
using Kokomo.Mirror.Ia32;
using Kokomo.Mirror;
using Kokomo.Mirror.PeFormat.Symbols;

namespace Kokomo.PeInspector
{
	public class PeModuleDisassemblyContext : IDisassemblyContext
	{
		public PeModuleDisassemblyContext(
			PeModule module,
			SymbolSource symbolSource = null
			)
		{
			if (module == null) throw new ArgumentNullException("module");

			this.Module = module;
			this.SymbolSource = symbolSource;

			if (module.Is64Bit)
				this.DefaultAddressSize = 64;
			else if (module.Is32Bit)
				this.DefaultAddressSize = 32;
			else
				this.DefaultAddressSize = 32;
		}

		public PeModule Module { get; private set; }
		public SymbolSource SymbolSource { get; private set; }

		public int DefaultAddressSize { get; private set; }

		public bool ReadData(long address, out int int32Value, out string stringValue)
		{
			if (!this.Module.IsValidAddress(address))
			{
				int32Value = 0;
				stringValue = null;
				return false;
			}

			uint rva = this.Module.AbsoluteToRva(address);
			return this.Module.ReadInitializedData(rva, out int32Value, out stringValue);
		}

		public SymbolicReference GetSymbolicReference(long address)
		{
			SymbolicReference reference = null;
			if (this.Module.IsValidAddress(address))
			{
				uint rva = this.Module.AbsoluteToRva(address);

				reference = this.Module.LookupSymbolicReference(rva);
				if (reference != null)
					return reference;

				if (this.SymbolSource != null)
				{
					reference = this.SymbolSource.GetSymbolicReferenceForRva(rva);
				}
			}

			return reference;
		}

		public string ResolveModule(string moduleName)
		{
			return this.Module.ResolveModule(moduleName);
		}


		public NativeProcedureInfo GetProcedure(long address)
		{
			if (this.Module.IsValidAddress(address))
				return this.Module.GetProcedureAtRva(this.Module.AbsoluteToRva(address));

			return null;
		}
	}
}
